
#ifndef STUDIO_MQTT_CLIENT_H
#define STUDIO_MQTT_CLIENT_H

#if ENABLE_PAHO_MQTT

#endif

#include <mqtt/async_client.h>
#include <studio_macros.h>

///////////// MQTT 发布 回调 //////////////

/// <summary>
/// 用于主 MQTT 客户端的回调类
/// </summary>
class pub_callback : public virtual mqtt::callback
{
  public:
    /// <summary>
    /// 当客户端与服务器断开连接时触发，打印断开原因。
    /// </summary>
    /// <param name="cause"></param>
    void connection_lost(const std::string& cause) override
    {
        std::cout << "\nConnection lost" << std::endl;
        if (!cause.empty())
            std::cout << "\tcause: " << cause << std::endl;
    }

    /// <summary>
    /// 当消息成功发送到服务器时触发，打印对应的令牌 ID。
    /// </summary>
    /// <param name="tok"></param>
    void delivery_complete(mqtt::delivery_token_ptr tok) override
    {
        std::cout << "\tDelivery complete for token: " << (tok ? tok->get_message_id() : -1) << std::endl;
    }
};

//////////////////////////////////////////////////////

/**
 * 基础动作监听器

 */
class pub_action_listener : public virtual mqtt::iaction_listener
{
  protected:

    /// <summary>
    /// 当动作 失败 时触发，打印失败的令牌 ID。
    /// </summary>
    /// <param name="tok"></param>
    void on_failure(const mqtt::token& tok) override
    {
        std::cout << "\tListener failure for token: " << tok.get_message_id() << std::endl;
    }

    /// <summary>
    /// 当某个动作成功时触发，打印成功的令牌 ID。
    /// </summary>
    /// <param name="tok"></param>
    void on_success(const mqtt::token& tok) override
    {
        std::cout << "\tListener success for token: " << tok.get_message_id() << std::endl;
    }
};

//////////////////////////////////////////////////////

/**
 * A derived action listener for publish events.
 * 继承自 action_listener，增加了 done_ 标志位，用于判断消息是否已成功发送。
 */
class pub_delivery_action_listener : public pub_action_listener
{
    std::atomic<bool> done_;

    void on_failure(const mqtt::token& tok) override
    {
        pub_action_listener::on_failure(tok);
        done_ = true;
    }

    void on_success(const mqtt::token& tok) override
    {
        pub_action_listener::on_success(tok);
        done_ = true;
    }

  public:
    pub_delivery_action_listener() : done_(false)
    {
    }
    bool is_done() const
    {
        return done_;
    }
};


///////////// MQTT 订阅 回调 //////////////

static const int qos_ = 1;
static const int N_RETRY_ATTEMPTS = 5;

// 动作监听器类
class subs_action_listener : public virtual mqtt::iaction_listener
{
    std::string name_;

    /// <summary>
    /// 当某个动作失败时触发，打印失败信息
    /// </summary>
    /// <param name="tok"></param>
    void on_failure(const mqtt::token& tok) override
    {
        std::cout << name_ << " failure";
        if (tok.get_message_id() != 0)
            std::cout << " for token: [" << tok.get_message_id() << "]" << std::endl;
        std::cout << std::endl;
    }

    /// <summary>
    /// 当某个动作成功时触发，打印成功信息及相关的主题
    /// </summary>
    /// <param name="tok"></param>
    void on_success(const mqtt::token& tok) override
    {
        std::cout << name_ << " success";
        if (tok.get_message_id() != 0)
            std::cout << " for token: [" << tok.get_message_id() << "]" << std::endl;
        auto top = tok.get_topics();
        if (top && !top->empty())
            std::cout << "\ttoken topic: '" << (*top)[0] << "', ..." << std::endl;
        std::cout << std::endl;
    }

  public:

    /// <summary>
    /// 构造函数接受一个名称参数，用于标识监听器
    /// </summary>
    /// <param name="name"></param>
    subs_action_listener(const std::string& name) : name_(name)
    {
    }
};


class subs_callback : public virtual mqtt::callback, public virtual mqtt::iaction_listener
{
    int nretry_;
    mqtt::async_client& cli_;
    mqtt::connect_options& connOpts_;
    subs_action_listener subListener_;
    std::string topic_name;
    std::string client_id;

    /// <summary>
    /// 手动重新连接到 MQTT 服务器，使用 cli_.connect() 方法
    /// </summary>
    void reconnect()
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(2500));
        try
        {
            cli_.connect(connOpts_, nullptr, *this);
        }
        catch (const mqtt::exception& exc)
        {
            std::cerr << "Error: " << exc.what() << std::endl;
            exit(1);
        }
    }

    /// <summary>
    /// 连接失败时触发，尝试重新连接，最多重试 N_RETRY_ATTEMPTS 次。
    /// </summary>
    /// <param name="tok"></param>
    void on_failure(const mqtt::token& tok) override
    {
        std::cout << "Connection attempt failed" << std::endl;
        if (++nretry_ > N_RETRY_ATTEMPTS)
            exit(1);
        reconnect();
    }

    /// <summary>
    /// 连接成功时触发
    /// </summary>
    /// <param name="tok"></param>
    void on_success(const mqtt::token& tok) override
    {
        std::cout << "Connection attempt succeeded" << std::endl;
    }

    /// <summary>
    /// 连接成功后订阅指定主题，并输出相关信息。
    /// </summary>
    /// <param name="cause"></param>
    void connected(const std::string& cause) override
    {
        std::cout << "\nConnection success" << std::endl;
        std::cout << "\nSubscribing to topic '" << topic_name << "'\n"
                  << "\tfor client " << client_id << " using QoS" << qos_ << "\n"
                  << "\nPress Q<Enter> to quit\n"
                  << std::endl;

        cli_.subscribe(topic_name, qos_, nullptr, subListener_);
    }

    /// <summary>
    /// 连接丢失时触发，尝试重新连接
    /// </summary>
    /// <param name="cause"></param>
    void connection_lost(const std::string& cause) override
    {
        std::cout << "\nConnection lost" << std::endl;
        if (!cause.empty())
            std::cout << "\tcause: " << cause << std::endl;

        std::cout << "Reconnecting..." << std::endl;
        nretry_ = 0;
        reconnect();
    }

    /// <summary>
    /// 当有新消息到达时触发，打印消息的主题和内容
    /// </summary>
    /// <param name="msg"></param>
    void message_arrived(mqtt::const_message_ptr msg) override
    {
        std::cout << "Message arrived" << std::endl;
        std::cout << "\ttopic: '" << msg->get_topic() << "'" << std::endl;
        std::cout << "\tpayload: '" << msg->to_string() << "'\n" << std::endl;
    }

    /// <summary>
    /// 消息发送完成时触发
    /// </summary>
    /// <param name="token"></param>
    void delivery_complete(mqtt::delivery_token_ptr token) override
    {
        std::cout << "Delivery complete for token: " << token->get_message_id() << std::endl;
    }


  public:
    subs_callback(mqtt::async_client& cli, mqtt::connect_options& connOpts, std::string topic_name, std::string client_id) : nretry_(0), cli_(cli), connOpts_(connOpts), subListener_("Subscription"), topic_name(topic_name), client_id(client_id)
    {
    }
};




class studio_mqtt_client
{
  public:

    bool publish(const std::string& topic, const std::string& payload);
    bool subscribe();

    bool check();
    void client_id(const std::string& ci);
    void user(const std::string& u);
    void password(const std::string& p);
    void host(const std::string& h);
    void port(const int& p);
    void qos(const int& q);
    void protocol(const std::string& p);
    void server(const std::string& s);
    void topic_name(const std::string& t);


    std::string m_client_id;         // 客户端ID
    std::string m_server;            //
    std::string m_user;              // 用户名
    std::string m_protocol{"mqtt"};  // 协议默认 mqtt
    std::string m_password;          // 密码
    std::string m_host;              // 主机地址
    int m_port{1883};                // 1883 默认非加密端口  8883 默认加密端口
    int m_qos{0};                    // QoS等级（默认0，最多一次）:0 最多一次  1 最少一次  2 只有一次
    std::string m_topic_name;           // 发布主题

    // 成员变量
    std::mutex m_mutex;
    //std::atomic<bool> m_connected{false};
    //std::atomic<bool> m_disconnecting{false};
    //std::shared_ptr<mqtt::async_client> m_client;
    bool m_connected;

};

#endif  // STUDIO_MQTT_CLIENT_H
